home *** CD-ROM | disk | FTP | other *** search
/ Macwelt 1 / Macwelt DVD 1.toast / Web-Publishing / HTML-Editoren / Alpha ƒ / Mode Examples / Tcl-Example.tcl < prev    next >
Encoding:
Text File  |  2000-10-30  |  38.2 KB  |  1,317 lines

  1. ## -*-Tcl-*-
  2.  # # ###################################################################
  3.  #  Alpha - new Tcl folder configuration
  4.  # 
  5.  #  FILE: "tclMode.tcl"
  6.  #                                    created: 5/4/97 {9:31:10 pm} 
  7.  #                                last update: 10/18/00 {11:21:29 am} 
  8.  #  Author: Vince Darley
  9.  #  E-mail: <vince@santafe.edu>
  10.  #    mail: 317 Paseo de Peralta
  11.  #          Santa Fe, NM 87501, USA
  12.  #     www: <http://www.santafe.edu/~vince/>
  13.  #  
  14.  # Copyright (c) 1997-2000 Vince Darley
  15.  #  
  16.  # Three procs from original: Tcl::DblClick listArray, getVarValue
  17.  #    
  18.  # Adds support for Tk, Itcl keywords and completions, plus 
  19.  # numerous fixes, improvements and integration with Vince's
  20.  # Additions.
  21.  # ###################################################################
  22.  ##
  23.  
  24. # Since this is included only for mode demonstration purposes, we make sure
  25. # that it never gets loaded.
  26. error "The \"Tcl-Example.tcl\" file should never be loaded !!"
  27.  
  28. alpha::mode Tcl 1.8.4 tclMenu {*.tcl *.itcl *.itk *.tbc tclIndex*} {
  29.     tclMenu electricTab electricReturn electricBraces alphaDeveloperMenu
  30. } {
  31.     addMenu tclMenu "•269" "Tcl" "Tcl menu\r\rnot very obvious..."
  32.     set unixMode(wish) {Tcl}
  33.     set unixMode(tclsh) {Tcl}
  34.     set unixMode(itclsh) {Tcl}
  35.     set unixMode(itkwish) {Tcl}
  36.     set unixMode(prowish) {Tcl}
  37.     set unixMode(protclsh) {Tcl}
  38.     ensureset tclshSig "WIsH"
  39.     ensureset evaluateRemotely 0
  40.     trace variable evaluateRemotely w tcltk::evaluateRemoteSynchronise
  41.     menu::buildProc tclMenu menu::buildtclMenu
  42.     lappend tclColourings Tcl::colorTclKeywords \
  43.       Tcl::colorTkKeywords \
  44.       Tcl::colorItclKeywords Tcl::colorPseudoTclKeywords \
  45.       Tcl::colorTkCommands Tcl::colorSymbols
  46. } maintainer {
  47.     "Vince Darley" vince@santafe.edu <http://www.santafe.edu/~vince/>
  48. } uninstall this-file help {
  49.     This mode is for editing Tcl code.  You can edit code for internal
  50.     use with Alpha, or use Alpha as an external editor for code destined
  51.     for use with Tcl and Tk interpreters --- Sun distributes the Wish
  52.     application and a tcl-tk browser plugin.
  53.     
  54.     You can 'evaluate' a procedure (or any Tcl code for that matter) to 
  55.     make changes on the fly.  If you select 'Evaluate Remotely' in the 
  56.     tcl-tk submenu, then such actions will actually send the code
  57.     to a separately running Wish application to be evaluated.
  58. }
  59.  
  60. namespace eval tcltk {}
  61. proc tclMenu {} {}
  62.  
  63. # ◊◊◊◊ menu and prefs ◊◊◊◊ #
  64. # The menu.
  65. proc menu::buildtclMenu {} {
  66.     global tclMenu evaluateRemotely tcltk::executables
  67.     set execs {}
  68.     if {[info exists tcltk::executables]} {
  69.     lappend execs "\(-"
  70.     foreach ex ${tcltk::executables} {
  71.         lappend execs [file tail $ex]
  72.     }
  73.     }
  74.     set ma [list \
  75.       "/Levaluate" "/-<UswitchToTclsh" \
  76.       [list Menu -n "tcl-tk" -p tcltk::menuProc [concat [list \
  77.       "![lindex {{ } •} $evaluateRemotely]evaluateRemotely" \
  78.       executeCommand executeFileInRemoteShell addWindowToListOfExecutables] \
  79.       $execs]] \
  80.       "\(-" "/L<O<BreloadProc" "/I<O<BreformatProc" \
  81.       "rebuildTclIndexForWin" "\(-" \
  82.       "<U/PfindProcDefinition…" "/Q<IquickFindProc…" "getVarValue…" \
  83.       "/4<BaddRemoveDollars" "/3<BinsertDivider" \
  84.       "\(-" "regularExpressionColors" "defaultColors"]
  85.     return [list build $ma Tcl::MenuProc "" $tclMenu]
  86. }
  87. menu::buildSome tclMenu
  88.  
  89. #===============================================================================
  90. #
  91. # Set up package-specific mode variables
  92.  
  93. # Removing obsolete preferences from earlier versions.
  94. prefs::removeObsolete TclmodeVars(alphaKeyWordColor) TclmodeVars(keywordColor)
  95.  
  96. newPref v prefixString {# } Tcl
  97. newPref f wordWrap {0} Tcl
  98. newPref v funcExpr {^proc *([+-a-zA-Z0-9]+)} Tcl
  99. newPref v parseExpr {^proc *([+-a-zA-Z0-9]+)} Tcl
  100. newPref v wordBreak {(\$)?[\w:_]+} Tcl
  101. newPref v wordBreakPreface {([^\w:_\$]|.\$)} Tcl
  102. newPref f autoMark 0 Tcl
  103. # Indentation scheme for lines following one ending in a backslash
  104. newPref v indentSlashEndLines 1 Tcl "" indent::amounts varindex
  105. # Mark files structurally, recognising the special comments
  106. # entered by 'ctrl-3'
  107. newPref f structuralMarks 0 Tcl
  108.  
  109. set Tcl::startPara {^(.*\{)?[ \t]*(#|$)}
  110. set Tcl::endPara {^(.*\})?[ \t]*(#|$)}
  111. set Tcl::commentRegexp {^[ \t]*#}
  112.  
  113. # Not sure if this is used by completions still...
  114. set Tclcmds { append array catch close concat continue elseif error
  115. for foreach format lindex llength lrange lreplace lsearch lsort regexp 
  116. regsub rename return string switch while }
  117.  
  118. #===============================================================================
  119. #
  120. # Colorization setup
  121. #
  122.  
  123. # Colour Tk commands
  124. newPref f recogniseTk        {1}    Tcl    {Tcl::updateColors}
  125. # Colour [incr Tcl] commands
  126. newPref f recogniseItcl        {1}    Tcl    {Tcl::updateColors}
  127. # Recognise and colour some common procedures 'lunion' etc.
  128. newPref f recognisePseudoTcl    {1}    Tcl    {Tcl::updateColors}
  129. # Colour of all chosen commands.
  130. newPref v commandColor        {blue}    Tcl    {Tcl::updateColors}
  131. # Color for Tcl comments
  132. newPref v commentColor        {red}    Tcl    {Tcl::updateColors}
  133. # Colour of the $ magic character.
  134. newPref v magicColor        {black}    Tcl    {Tcl::updateColors}
  135. # Colour for strings
  136. newPref v stringColor        {green}    Tcl    {Tcl::updateColors}
  137. # Colour of symbols such as \, -, +, *, etc.  Can be useful for
  138. # reading regular expressions.
  139. newPref v symbolColor        {black}    Tcl    {Tcl::updateColors}
  140.  
  141. ## 
  142.  # -------------------------------------------------------------------------
  143.  # 
  144.  # "Tcl::_updateKeywords" --
  145.  # 
  146.  #  This proc now includes support for optional separate colorization of 
  147.  #  alpha commands. To use, set 'alphaKeyWordColor' to something other than 
  148.  #  'none' in the Tcl Mode Preferences dialog. -trf
  149.  # -------------------------------------------------------------------------
  150.  # 
  151.  # Now split into a series of procs, called in the end by colorizeTcl.  -cbu
  152.  # 
  153.  # -------------------------------------------------------------------------
  154.  ##
  155.  
  156. #===============================================================================
  157. #
  158. # Color procs begin here #
  159. #
  160.  
  161.  
  162. #===============================================================================
  163. #
  164. # Color Tcl Keywords
  165. #
  166.  
  167. proc Tcl::colorTclKeywords {} {
  168.     global TclmodeVars
  169.  
  170.     # all except beep and echo are basic Tcl keywords
  171.  
  172.     set tclKeyWords {
  173.     after append array auto_execok auto_import auto_load
  174.     auto_load_index auto_qualify beep binary break case catch cd clock
  175.     close concat continue dde default echo else elseif encoding eof
  176.     error eval exec exit expr fblocked fconfigure fcopy file
  177.     fileevent flush for foreach format gets glob global history if
  178.     incr info interp join lappend lindex linsert list llength load
  179.     lrange lreplace lsearch lsort namespace open package pid
  180.     pkg_mkIndex proc puts pwd read regexp regsub rename resource
  181.     return scan seek set socket source split string subst switch
  182.     tclLog tclMacPkgSearch tclPkgSetup tclPkgUnknown tell time
  183.     trace unknown unset update uplevel upvar variable vwait while
  184.     }
  185.     
  186.     regModeKeywords -a                \
  187.       -e {#} -c $TclmodeVars(commentColor)      \
  188.       -s $TclmodeVars(stringColor)              \
  189.       -k $TclmodeVars(commandColor) Tcl      \
  190.       $tclKeyWords 
  191.  
  192. }
  193.  
  194.  
  195.  
  196.  
  197. #===============================================================================
  198. #
  199. # Color Tk Keywords
  200. #
  201.  
  202. proc Tcl::colorTkKeywords {} {
  203.     global TclmodeVars
  204.  
  205.     set tkKeyWords {
  206.     bell bind bindtags button canvas checkbutton console destroy
  207.     entry event focus font frame grab grid image label listbox menu
  208.     menubutton message pack place radiobutton raise scale scrollbar
  209.     text tk tkwait toplevel winfo wm
  210.     }
  211.  
  212.     if {$TclmodeVars(recogniseTk)} {
  213.      regModeKeywords -a             \
  214.       -k $TclmodeVars(commandColor) Tcl    \
  215.       $tkKeyWords
  216.     } else {
  217.      regModeKeywords -a             \
  218.       -k {black} Tcl            \
  219.       $tkKeyWords
  220.     }
  221. }
  222.  
  223.  
  224. #===============================================================================
  225. #
  226. # Color iTcl Keywords
  227. #
  228.  
  229. proc Tcl::colorItclKeywords {} {
  230.     global TclmodeVars
  231.  
  232.     set itclKeyWords {
  233.     @scope body class code common component configbody constructor
  234.     define destructor hull import inherit itcl itk itk_component
  235.     itk_initialize itk_interior itk_option iwidgets keep method
  236.     private protected public
  237.     }
  238.  
  239.     if {$TclmodeVars(recogniseItcl)} {
  240.     regModeKeywords -a                 \
  241.      -k $TclmodeVars(commandColor) Tcl         \
  242.      $itclKeyWords
  243.    } else {
  244.     regModeKeywords -a                 \
  245.      -k {black} Tcl                     \
  246.      $itclKeyWords
  247.    }
  248. }
  249.  
  250.  
  251. #===============================================================================
  252. #
  253. # Color Pseudo Tcl Keywords
  254. #
  255.  
  256. proc Tcl::colorPseudoTclKeywords {} {
  257.     global TclmodeVars
  258.     
  259.     set PseudoTclKeywords { 
  260.     lcontains lunion lreverse lremove lunique
  261.     }
  262.     if {$TclmodeVars(recogniseTk)} {
  263.     regModeKeywords -a                 \
  264.      -k $TclmodeVars(commandColor) Tcl         \
  265.      $PseudoTclKeywords
  266.     } else {
  267.     regModeKeywords -a                 \
  268.      -k {black} Tcl                     \
  269.      $PseudoTclKeywords
  270.     }
  271.     
  272. }
  273.  
  274.  
  275. #===============================================================================
  276. #
  277. # Color Tk Commands
  278. #
  279. # add this line if we can handle double 'magic chars'
  280. # -m {tk} 
  281. #
  282.  
  283. proc Tcl::colorTkCommands {} {
  284.     
  285.     global TclmodeVars
  286.  
  287.     set TkCommands {
  288.     tkButtonDown tkButtonEnter tkButtonInvoke tkButtonLeave tkButtonUp
  289.     tkCancelRepeat tkCheckRadioInvoke tkDarken tkEntryAutoScan
  290.     tkEntryBackspace tkEntryButton1 tkEntryClosestGap tkEntryInsert
  291.     tkEntryKeySelect tkEntryMouseSelect tkEntryNextWord tkEntryPaste
  292.     tkEntryPreviousWord tkEntrySeeInsert tkEntrySetCursor
  293.     tkEntryTranspose tkEventMotifBindings tkFDGetFileTypes tkFirstMenu
  294.     tkFocusGroup_BindIn tkFocusGroup_BindOut tkFocusGroup_Create
  295.     tkFocusGroup_Destroy tkFocusGroup_In tkFocusGroup_Out tkFocusOK
  296.     tkListboxAutoScan tkListboxBeginExtend tkListboxBeginSelect
  297.     tkListboxBeginToggle tkListboxCancel tkListboxDataExtend
  298.     tkListboxExtendUpDown tkListboxMotion tkListboxSelectAll
  299.     tkListboxUpDown tkMbButtonUp tkMbEnter tkMbLeave tkMbMotion
  300.     tkMbPost tkMenuButtonDown tkMenuDownArrow tkMenuDup tkMenuEscape
  301.     tkMenuFind tkMenuFindName tkMenuFirstEntry tkMenuInvoke tkMenuLeave
  302.     tkMenuLeftArrow tkMenuMotion tkMenuNextEntry tkMenuNextMenu
  303.     tkMenuRightArrow tkMenuUnpost tkMenuUpArrow tkMessageBox
  304.     tkPostOverPoint tkRecolorTree tkRestoreOldGrab tkSaveGrabInfo
  305.     tkScaleActivate tkScaleButton2Down tkScaleButtonDown
  306.     tkScaleControlPress tkScaleDrag tkScaleEndDrag tkScaleIncrement
  307.     tkScreenChanged tkScrollButton2Down tkScrollButtonDown
  308.     tkScrollButtonUp tkScrollByPages tkScrollByUnits tkScrollDrag
  309.     tkScrollEndDrag tkScrollSelect tkScrollStartDrag tkScrollToPos
  310.     tkScrollTopBottom tkTabToWindow tkTearOffMenu tkTextAutoScan
  311.     tkTextButton1 tkTextClosestGap tkTextInsert tkTextKeyExtend
  312.     tkTextKeySelect tkTextNextPara tkTextNextPos tkTextNextWord
  313.     tkTextPaste tkTextPrevPara tkTextPrevPos tkTextResetAnchor
  314.     tkTextScrollPages tkTextSelectTo tkTextSetCursor tkTextTranspose
  315.     tkTextUpDownLine tkTraverseToMenu tkTraverseWithinMenu tk_bisque
  316.     tk_chooseColor tk_dialog tk_focusFollowsMouse tk_focusNext
  317.     tk_focusPrev tk_getOpenFile tk_getSaveFile tk_messageBox
  318.     tk_optionMenu tk_popup tk_setPalette tk_textCopy tk_textCut
  319.     tk_textPaste
  320.     }
  321.     
  322.     if {$TclmodeVars(recogniseTk)} {
  323.     regModeKeywords -a             \
  324.      -k $TclmodeVars(commandColor) Tcl     \
  325.      $TkCommands
  326.     } else {
  327.     regModeKeywords -a             \
  328.      -k {black} Tcl             \
  329.      $TkCommands   
  330.  
  331.     }
  332.     unset TkCommands    
  333. }
  334.  
  335.     
  336. #===============================================================================
  337. #
  338. # Color Symbols and Magic Character
  339.  
  340. proc Tcl::colorSymbols {} {
  341.     
  342.     global TclmodeVars
  343.     
  344.     regModeKeywords -a                 \
  345.       -m {$}                    \
  346.       -k $TclmodeVars(magicColor) Tcl {}    \
  347.       -i "+" -i "-" -i "*" -i "_" -i "\\"    \
  348.       -I $TclmodeVars(symbolColor)  
  349. }
  350.  
  351.  
  352. #===============================================================================
  353. #
  354. # Colorize Tcl
  355.  
  356. proc Tcl::colorizeTcl {} {
  357.     global tclColourings
  358.     foreach p $tclColourings {
  359.     $p
  360.     }
  361.     refresh
  362. }
  363.  
  364. # This is a "dummy" command, necessary for the above proc so that all of
  365. # the "regModeKeywords" commands in the called color procs can be "adds"
  366. # (-a).  When the mode is first invoked, this has to occur before the color
  367. # procs are called.
  368.  
  369. regModeKeywords -k {none} Tcl {}
  370.  
  371. # now we finally colorize
  372.  
  373. Tcl::colorizeTcl
  374.  
  375.     
  376. #===============================================================================
  377. #
  378. # Tcl:: Update Colors -- 
  379. # This allows for changes to take effect without a restart.
  380. # Danger:  Don't include this proc in any {mode}Prefs.tcl file !!!
  381. # This will source the prefs file, and thus put Alpha in an endless loop.
  382. # Instead, use the  Tcl::colorizeTcl  proc in the prefs file, so that
  383. # "Load Prefs File" will update any local variables.     - cbu
  384.  
  385.  
  386. proc Tcl::updateColors {flag} {
  387.     
  388.     global mode PREFS $flag TclmodeVars 
  389.     
  390.     # If the mode has a {mode}Prefs.tcl file, we want to load that as 
  391.     # well, otherwise any keywords contained therein won't be updated
  392.     # without a manual "Load Prefs File".
  393.     
  394.     if {[file exists [file join ${PREFS} ${mode}Prefs.tcl]]} {
  395.     uplevel #0 [list source [file join ${PREFS} ${mode}Prefs.tcl]]
  396.     } 
  397.  
  398.     Tcl::colorizeTcl
  399. }
  400.  
  401. #===============================================================================
  402. #
  403. # Regular Expression Colors --
  404. # Changes color scheme of current window to make it easier to read regular
  405. # expressions.  Preferences aren't actually changed.  "defaultColors" will
  406. # restore to the last stored values of the colors.  -cbu
  407.  
  408. proc Tcl::regularExpressionColors {} {
  409.     
  410.     regModeKeywords -a                 \
  411.       -e {}                    \
  412.       -m {$}                    \
  413.       -s {black}                \
  414.       -k {magenta} Tcl {}            \
  415.       -i "+" -i "-" -i "*" -i "_" -i "\\"    \
  416.       -I {red}  
  417.     
  418.     refresh
  419. }
  420.  
  421. proc Tcl::defaultColors {} {Tcl::colorizeTcl}
  422.     
  423.  
  424. # ???? end of keyword colorizing ???? #
  425.  
  426. #===============================================================================
  427.  
  428.  
  429. proc Tcl::MenuProc {menu item} {
  430.     switch -glob $item {
  431.     "reformatProc" {
  432.         procs::reformatEnclosing [getPos]
  433.     }
  434.     "reloadProc" {
  435.         procs::loadEnclosing [getPos]
  436.     }
  437.     "findProcDefinition" {
  438.         procs::findDefinition
  439.     }
  440.     "quickFindProc" {
  441.         # use the status line
  442.         procs::quickFindDefn
  443.     }
  444.     "switch*" {
  445.         set v "[string tolower [string range $item 8 end]]Sig"
  446.         global $v
  447.         app::launchFore [set $v]
  448.     }
  449.     "addRemoveDollars" {
  450.         togglePrefix \$
  451.     }
  452.     default {
  453.         menu::generalProc Tcl $item 0
  454.     }
  455.     }
  456. }
  457.  
  458. ## 
  459.  # -------------------------------------------------------------------------
  460.  # 
  461.  # "Tcl::rebuildTclIndexForWin" --
  462.  # 
  463.  #  If the file is in Alpha's source tree, use the currently loaded
  464.  #  auto_mkindex.  If it is not, then fire up a separate Tcl application
  465.  #  and use its auto_mkindex (i.e. the standard Tcl one).  It just occured
  466.  #  to me that for Tcl >= 8.0, we could create a new interp, and 
  467.  #  execute auto_mkindex within that to the same effect, but without
  468.  #  the overhead of a whole new process (especially a Tk one!).
  469.  # -------------------------------------------------------------------------
  470.  ##
  471. proc Tcl::rebuildTclIndexForWin {} {
  472.     if {[alpha::inAlphaHierarchy [win::Current]]} {
  473.     auto_mkindex [file dirname [win::Current]]
  474.     auto_reset
  475.     } else {
  476.     # This will currently launch a Tk shell, which isn't ideal.
  477.     set dir [file dirname [win::Current]]
  478.     tcltk::launchNewShell "auto_mkindex $dir" "exit"
  479.     }
  480. }
  481.  
  482. proc tcltk::menuProc {menu item} {
  483.     global tcl_platform tclshSig
  484.     switch -- $item {
  485.     "evaluateRemotely" {
  486.         global evaluateRemotely
  487.         set evaluateRemotely [expr {1 - $evaluateRemotely}]
  488.     }
  489.     "executeFileInRemoteShell" {
  490.         tcltk::executeInRemoteShell [win::Current]
  491.     }
  492.     "addWindowToListOfExecutables" {
  493.         global tcltk::executables
  494.         lappend tcltk::executables [win::Current]
  495.         prefs::modified tcltk::executables
  496.         menu::buildSome tclMenu
  497.     }
  498.     "executeCommand" {
  499.         set cmd [getline "Please enter the script to send to tcl-tk"]
  500.         if {$cmd == ""} {return}
  501.         if {$tcl_platform(platform) == "macintosh"} {
  502.         set res [AEBuild -r -t 30000 '$tclshSig' misc dosc ---- "“$cmd”"]
  503.         } else {
  504.         set res [tcltk::evaluate $cmd]
  505.         }
  506.         alertnote "Result was '$res'"
  507.     }
  508.     default {
  509.         global tcltk::executables
  510.         foreach ex ${tcltk::executables} {
  511.         if {[file tail $ex] == $item} {
  512.             tcltk::executeInRemoteShell $ex
  513.             break
  514.         }
  515.         }
  516.     }
  517.     }
  518. }
  519.  
  520. proc tcltk::executeInRemoteShell {f} {
  521.     global evaluateRemotely
  522.     set realName [stripNameCount $f]
  523.     tcltk::launchNewShell \
  524.       "cd [file dirname $realName]" \
  525.       "source [file tail $realName]"
  526.     if {!$evaluateRemotely} {
  527.     set evaluateRemotely 1
  528.     }
  529. }
  530.  
  531. proc tcltk::evaluateRemoteSynchronise {args} {
  532.     global evaluateRemotely tclMenu
  533.     catch {markMenuItem "tcl-tk" evaluateRemotely $evaluateRemotely}
  534.     if {$evaluateRemotely} {
  535.     if {[info commands notRemoteEvaluate] == ""} {
  536.         rename evaluate notRemoteEvaluate
  537.         ;proc evaluate {} {remoteEvaluate}
  538.     }
  539.     menu::replaceRebuild tclMenu "•320"
  540.     } else {
  541.     if {[info commands notRemoteEvaluate] != ""} {
  542.         rename evaluate {}
  543.         rename notRemoteEvaluate evaluate
  544.     }
  545.     menu::replaceRebuild tclMenu "•269"
  546.     }
  547. }
  548.  
  549.  
  550. proc remoteEvaluate {} {
  551.     message "Remote reply: [tcltk::evaluate [getSelect]]"
  552. }
  553.  
  554. proc tcltk::evaluate {what} {
  555.     global tclshSig tcl_platform
  556.     if {$tcl_platform(platform) == "macintosh"} {
  557.     app::ensureRunning $tclshSig
  558.     if {[catch {set r [tclAE::build::resultData -t 30000 '${tclshSig}' \
  559.                 misc dosc \
  560.               ---- [tclAE::build::TEXT $what] \
  561.             ]} res]} {
  562.         set res "Error: $res"
  563.     }            
  564.     #catch {dosc -c '${tclshSig}' -s $what} res
  565.     #return $res
  566.     } else {
  567.     global tclshInterp
  568.     if {![info exists tclshInterp]} {
  569.         if {[catch {tcltk::findTclshInterp}]} {
  570.         return "No shell selected"
  571.         }
  572.     }
  573.     if {$tcl_platform(platform) == "windows"} {
  574.         if {[dde services TclEval $tclshInterp] == ""} {
  575.         alertnote "The remote shell has died, please select a new one."
  576.         unset tclshInterp
  577.         return [tcltk::evaluate $what]
  578.         }
  579.         dde execute TclEval $tclshInterp [list catch $what alpha_result]
  580.         return [dde request TclEval $tclshInterp alpha_result]
  581.     } else {
  582.         catch {send $tclshInterp $what} res
  583.     }
  584.     }
  585.     return $res
  586. }
  587.  
  588. proc tcltk::listInterps {} {
  589.     global tcl_platform
  590.     if {$tcl_platform(platform) == "windows"} {
  591.     set res {}
  592.     foreach service [dde services TclEval ""] {
  593.         lappend res [lindex $service 1]
  594.     }
  595.     return $res
  596.     } else {
  597.     return [winfo interps]
  598.     }
  599. }
  600.  
  601. proc tcltk::findTclshInterp {} {
  602.     global tclshInterp tclshSigs tclshSig
  603.     set old [tcltk::listInterps]
  604.     set shel [listpick -p "Use which Tcl shell?" [concat $old \
  605.       [list "------------------" "Launch new shell"]]]
  606.     if {$shel == "Launch new shell"} {
  607.     tcltk::launchNewShell
  608.     } else {
  609.     set tclshInterp $shel
  610.     }
  611. }
  612.  
  613. ## 
  614.  # -------------------------------------------------------------------------
  615.  # 
  616.  # "tcltk::launchNewShell" --
  617.  # 
  618.  #  Startup up a new Tcl shell, ensuring that we can communicate with that
  619.  #  shell.  On Unix/MacOS this should be easy using 'send' or apple-events
  620.  #  respectively.  On Windows we have to set up the new shell as a dde
  621.  #  server.  We do this with the script 'winRemoteShell.tcl'.
  622.  #  
  623.  #  Any extra 'args' passed to this procedure are executed, one by one,
  624.  #  in the new shell.
  625.  # -------------------------------------------------------------------------
  626.  ##
  627. proc tcltk::launchNewShell {args} {
  628.     global tclshInterp tclshSigs tclshSig tcl_platform HOME
  629.     set old [tcltk::listInterps]
  630.     if {$tcl_platform(platform) == "windows"} {
  631.     app::runScript tclsh "Tcl shell" [file join $HOME Tools winRemoteShell.tcl] 1
  632.     } else {
  633.     app::launchElseTryThese $tclshSigs tclshSig "Please locate the remote Tcl application"
  634.     }
  635.     while {[tcltk::listInterps] == $old} {
  636.     update
  637.     }
  638.     set tclshInterp [lremove -l [tcltk::listInterps] $old]
  639.     # We're left with two items
  640.     set tclshInterp [lindex $tclshInterp 0]
  641.     
  642.     if {[llength $args]} {
  643.     foreach arg $args {
  644.         tcltk::evaluate $arg
  645.     }
  646.     }
  647. }
  648.  
  649. # ◊◊◊◊ Quick Find Proc… ◊◊◊◊ #
  650.  
  651. proc procs::quickFindDefn {} {
  652.     Tcl::DblClickHelper [prompt::statusLineComplete "proc" procs::complete]
  653. }
  654.  
  655. if {[info tclversion] < 8.0} {
  656.     proc procs::complete {pref} {
  657.     return [info commands ${pref}*]
  658.     }
  659. } else {
  660.     proc procs::complete {pref} {
  661.     if {[regexp {(.*)([^:]+)$} $pref "" start tail]} {
  662.         set cmds [info commands ${pref}*]
  663.         foreach child [namespace children ::$start] {
  664.         if {[string match "::${tail}*" $child]} {
  665.             foreach cmd [info commands ${start}${child}::*] {
  666.             lappend cmds [string trimleft $cmd :]
  667.             }
  668.         }
  669.         }
  670.         return $cmds
  671.     } else {
  672.         return [info commands ${pref}*]
  673.     }
  674.     }
  675. }
  676.  
  677. # ◊◊◊◊ electric behaviour ◊◊◊◊ #
  678. proc Tcl::electricLeft {} {
  679.     if {[literalChar]} { insertText "\{"; return }
  680.     set pat "\}\[ \t\r\n\]*(else(if)?)\[ \t\r\n\]*\$"
  681.     set p [getPos]
  682.     if { [set res [findPatJustBefore "\}" "$pat" $p word]] == "" } { 
  683.     insertText "\{"
  684.     return
  685.     }
  686.     # we have an if/else(if)/else
  687.     switch -- $word {
  688.     "else" {
  689.         replaceText [lindex $res 0] $p "\} $word \{\r"
  690.         bind::IndentLine
  691.     }
  692.     "elseif" {
  693.         replaceText [lindex $res 0] $p "\} $word \{"
  694.     }
  695.     }
  696. }
  697.     
  698. proc Tcl::electricRight {} {
  699.     if {[literalChar]} { insertText "\}"; return }
  700.     set p [getPos]
  701.     if { [regexp "\[^ \t\]" [getText [lineStart $p] $p]] } {
  702.     insertText "\}"
  703.     blink [matchIt "\}" [pos::math $p - 1]]
  704.     return
  705.     }
  706.     set start [lineStart $p]
  707.     insertText "\}"
  708.     createTMark tcl_er [getPos]
  709.     backwardChar
  710.     bind::IndentLine
  711.     gotoTMark tcl_er ; removeTMark tcl_er
  712.     bind::CarriageReturn
  713.     blink [matchIt "\}" [pos::math $start - 1]]
  714. }
  715.  
  716. ## 
  717.  # -------------------------------------------------------------------------
  718.  # 
  719.  # "Tcl::correctIndentation" --
  720.  # 
  721.  #  Returns the correct indentation for the line containing $pos, if that
  722.  #  line were to contain ordinary characters only.  It is the 
  723.  #  responsibility of the calling procedure to ensure that if we are to
  724.  #  insert/have a line already, that that information is taken into
  725.  #  account, by passing in the argument 'next'
  726.  # -------------------------------------------------------------------------
  727.  ##
  728. proc Tcl::correctIndentation {pos {next ""}} {
  729.     global indent_amounts indentSlashEndLines
  730.     # preliminaries
  731.     if {[pos::compare [set beg [lineStart $pos]] == [minPos]]} { return 0 }
  732.     # if the current line is a comment, we have to check some
  733.     # special cases
  734.     if {[string index $next 0] == "\#"} {
  735.     set p [prevLineStart $beg]
  736.     if {[catch {set p [search -s -f 0 -r 1 -i 0 -m 0 "^\[ \t\]*\[^ \t\r\n\]" \
  737.       [pos::math $beg - 1]]}]} {
  738.         # check for search bug at beginning of file.
  739.         if {[pos::compare $p == [minPos]]} {
  740.         if {[getText [minPos] [pos::math [minPos] + 2]] == "\#\#"} {
  741.             if {([string range $next 0 1] != "\#\#")} {
  742.             return 1
  743.             } else {
  744.             return 0
  745.             }
  746.         }
  747.         }
  748.         return 0
  749.     }
  750.     set prev [pos::math [lindex $p 1] - 1]
  751.     set p [lindex $p 0]
  752.     if {[lookAt $prev] != "\#" || ($beg == [minPos])} {
  753.         # not a comment, so indent with code
  754.     } else {
  755.         set lwhite [posX $prev]
  756.         # it's a comment
  757.         if {[getText $prev [pos::math $prev + 2]] == "\#\#" && \
  758.           [lookAt [pos::math $prev + 2]] != "\#" \
  759.           && ([string range $next 0 1] != "\#\#")} {
  760.         # it's a comment paragraph
  761.         incr lwhite 
  762.         }
  763.     }
  764.     }
  765.     set next [string index $next 0]
  766.     if {![info exists lwhite]} {
  767.     if {![catch {search -s -f 0 -r 1 -i 0 -m 0 "^\[ \t\]*\[^\# \t\r\n\]" [pos::math $beg - 1]} lst]} {
  768.         # Find the last non-comment line and get its leading whitespace    
  769.         set lwhite [posX [pos::math [lindex $lst 1] - 1]]
  770.         set pe1 [lookAt [pos::math $beg - 2]]
  771.         set lst [lindex $lst 0]
  772.         set lastC [lookAt [lindex [search -s -f 0 -r 1 -i 0 -m 0 "\[^ \t\r\n\]" [pos::math [nextLineStart $lst] - 1]] 0]]
  773.         if {$next == "\}"} {
  774.         incr lwhite $indent_amounts(-2)
  775.         set pe2 [lookAt [pos::math [prevLineStart $beg] - 2]]
  776.         if {$pe1 == "\\"} {
  777.             incr lwhite $indent_amounts(1)
  778.         } else {
  779.             if {$pe2 == "\\"} {
  780.             incr lwhite $indent_amounts(-1)
  781.             }
  782.         }
  783.         if {$lastC == "\{"} {incr lwhite $indent_amounts(2)}    
  784.         } else { 
  785.         if {$pe1 == "\\"} {
  786.             if {[lookAt [pos::math [prevLineStart $beg] - 2]] != "\\"} {
  787.             incr lwhite $indent_amounts($indentSlashEndLines)
  788.             }
  789.         } else {
  790.             if {$lastC == "\{"} {incr lwhite $indent_amounts(2)}    
  791.             if {[lookAt [pos::math $lst - 2]] == "\\"} {
  792.             incr lwhite $indent_amounts(-$indentSlashEndLines)
  793.             }
  794.         }
  795.         }
  796.     } else {
  797.         # basically failed in all the above, so keep current indentation
  798.         set lwhite [posX [text::firstNonWsLinePos $beg]]
  799.     }
  800.     }
  801.     return [expr {$lwhite > 0 ? $lwhite : 0}]
  802. }
  803.  
  804. ## 
  805.  # -------------------------------------------------------------------------
  806.  #   
  807.  # "Tcl::indentLine" --
  808.  #  
  809.  #  Indentation for Tcl mode.  Better and faster than the generic procedure
  810.  # -------------------------------------------------------------------------
  811.  ##
  812. proc Tcl::indentLine {} {
  813.     set beg [lineStart [getPos]]
  814.     set text [getText $beg [nextLineStart $beg]]
  815.     regexp "^\[ \t\]*" $text white
  816.     set next [pos::math $beg + [string length $white]]
  817.     set nextp [pos::math $next + 2]
  818.     if {[pos::compare $nextp > [maxPos]]} {
  819.     set nextp [maxPos]
  820.     }
  821.     set lwhite [Tcl::correctIndentation [getPos] [getText $next $nextp]]
  822.     
  823.     set lwhite [text::indentOf $lwhite]
  824.     if {$white != $lwhite} {
  825.     replaceText $beg $next $lwhite
  826.     }
  827.     goto [pos::math $beg + [string length $lwhite]]
  828. }
  829. # ◊◊◊◊ Tcl Menu support ◊◊◊◊ #
  830.  
  831. proc procs::reformatEnclosing {pos} {
  832.     set p [procs::findEnclosing $pos "proc|((itcl::)?(body|configbody))" 0 1]
  833.     eval select $p
  834.     ::indentRegion
  835. }
  836.  
  837. proc procs::loadEnclosing {pos} {
  838.     if {[catch {procs::findEnclosing $pos "proc|((itcl::)?(body|configbody))" 0 1} p]} {
  839.     evaluateLine $pos
  840.     } else {
  841.     eval select $p
  842.     if {[catch {uplevel \#0 evaluate} err]} {
  843.         if {[regexp {can't create procedure "(.*)": unknown namespace} $err "" pr]} {
  844.         if {[dialog::yesno "The procedure '$pr' couldn't be loaded, because\
  845.           it is in an unknown namespace.  Shall I create the namespace and\
  846.           try again?"]} {
  847.             ensureNamespaceExists $pr
  848.             return [procs::loadEnclosing $pos]
  849.         }
  850.         }
  851.     }
  852.     }
  853.     goto $pos
  854. }
  855.  
  856. proc procs::findDefinition {} {
  857.     if {[llength [winNames]] && [string length [set sel [getSelect]]]} {
  858.     set func [listpick -L $sel -p {Proc?} [lsort -ignore [info procs]]]
  859.     } else {
  860.     set func [listpick -p {Proc?} [lsort -ignore [info procs]]]
  861.     }
  862.     
  863.     editMark [procs::find $func] $func
  864. }
  865.  
  866. ## 
  867.  # -------------------------------------------------------------------------
  868.  # 
  869.  # "insertDivider" --
  870.  # 
  871.  #  Modified from Vince's original to allow you to just select part of
  872.  #  an already written comment and turn it into a Divider. -trf
  873.  # -------------------------------------------------------------------------
  874.  ##
  875. proc insertDivider {} {
  876.     if {[isSelection]} {
  877.     set enfoldThis [getSelect]
  878.     beginningOfLine
  879.     killLine
  880.     insertText "# ◊◊◊◊ $enfoldThis ◊◊◊◊ #"
  881.     return
  882.     } 
  883.     elec::Insertion "# ◊◊◊◊ •• ◊◊◊◊ #"
  884. }
  885.  
  886. # ◊◊◊◊ Info providers ◊◊◊◊ #
  887. #===============================================================================
  888.  
  889.  
  890. proc Tcl::DblClick {from to shift option control} {
  891.     
  892.     # if cmd and cntrl were pressed, we look to select part of
  893.     # a combination word (less any leading dollar sign) -trf
  894.     if {$control != 0} {
  895.     set clickedPos [getPos]    
  896.     if {[lookAt $from] == "\$"} {
  897.         set from [pos::math $from + 1]
  898.     } 
  899.     set sel_start $clickedPos 
  900.     set selStartNotDetermined 1
  901.     while {$selStartNotDetermined && ([pos::math $sel_start > $from])} {
  902.         set char [lookAt $sel_start] 
  903.         if {[regexp {_} $char]} {
  904.         set sel_start [pos::math $sel_start + 1]
  905.         set selStartNotDetermined 0
  906.         } elseif {[regexp {[A-Z]} $char]} {
  907.         set selStartNotDetermined 0
  908.         } else {
  909.         set sel_start [pos::math $sel_start -1]
  910.         } 
  911.     }
  912.     set sel_end   $clickedPos 
  913.     set selEndNotDetermined 1
  914.     while {$selEndNotDetermined && ([pos::math $sel_end <= $to])} {
  915.         set char [lookAt $sel_end] 
  916.         if {[regexp "\[A-Z_ \t\r\]" $char]} {
  917.         set selEndNotDetermined 0
  918.         } else {
  919.         set sel_end [pos::math $sel_end + 1]
  920.         } 
  921.     }
  922.     select $sel_start $sel_end 
  923.     return
  924.     } 
  925.     
  926.     # otherwise, we try to impart some extra info
  927.     select $from $to
  928.     
  929.     if {[catch {Tcl::DblClickHelper [getSelect]}]} {
  930.     message "No docs $shift $control $option"
  931.     }
  932. }
  933.  
  934.  
  935. # Now finds commands in Alpha Commands,
  936. # which has a <cr> immediately after them, e.g. beep, ticks.
  937. proc Tcl::DblClickHelper {text} {
  938.     global HOME auto_index auto_path
  939.     # Is it a loadable proc?
  940.     if {[string length [set f [procs::find $text]]]} {
  941.     if {[editMark $f $text]} {
  942.         # some marking schemes commonly used for Tcl modes
  943.         goto [lindex [search -s -f 1 -r 1 -m 0 -- "proc\[ \t\]+${text}" [minPos]] 0]
  944.     }
  945.     return
  946.     }
  947.     
  948.     if {[info exists "auto_index($text)"]} {
  949.     if {[editMark "$auto_index($text)" $text]} {
  950.         # some marking schemes commonly used for Tcl modes
  951.         goto [lindex [search -s -f 1 -r 1 -m 0 -- "proc\[ \t\]+${text}" [minPos]] 0]
  952.     }
  953.     return
  954.     }
  955.     # Is it a built-in Alpha command?
  956.     set lines [grep "^• $text\( |\$)" [file join $HOME Help "Alpha Commands"]]
  957.     if {[string length $lines]} {
  958.     if {[catch {editMark [file join $HOME Help "Alpha Commands"] $text}]} {
  959.         # mark failed for some reason, but we have the line number
  960.         # anyway.
  961.         file::openQuietly [file join $HOME Help "Alpha Commands"]
  962.         goto [rowColToPos [string trimright [lindex [lindex [split $lines "\n"] 1] 3] :] 0]
  963.     }
  964.     setWinInfo read-only 1
  965.     return
  966.     }
  967.     # Is it a core Tcl command?
  968.     set lines [grep "^     $text -" [file join $HOME Help "Tcl Commands"]]
  969.     if {[string length $lines]} {
  970.     if {[catch {editMark [file join $HOME Help "Tcl Commands"] $text}]} {
  971.         # mark failed for some reason, but we have the line number
  972.         # anyway.
  973.         file::openQuietly [file join $HOME Help "Tcl Commands"]
  974.         goto [rowColToPos [string trimright [lindex [lindex [split $lines "\n"] 1] 3] :] 0]
  975.     }
  976.     setWinInfo read-only 1
  977.     return
  978.     }
  979.     # Is it a global variable?
  980.     if {[llength [info globals [string trimleft $text {$}]]]==1} {
  981.     showVarValue [string trimleft $text {$}]
  982.     return
  983.     }
  984.     # (becoming desperate) is it a mark in the current file?
  985.     if {[lsearch [getNamedMarks -n] ${text}] != -1} {
  986.     gotoMark $text
  987.     return
  988.     }
  989.     error ""
  990. }
  991.  
  992. #############################################################################
  993. #  Report the current value of a global variable, chosen interactively
  994. #  from a list of all active variables.
  995. #
  996. #  If the variable is an array, or its value is too big to fit in an 
  997. #  alertnote, then its contents are listed in a new window, otherwise 
  998. #  the variable's value is displayed in an alertnote.
  999. #
  1000. proc getVarValue {} {
  1001.     if {[catch {getText [getPos] [selEnd]} def]} {set def ""}
  1002.     set var [getVarFromList $def]
  1003.     if {[string length $var] == 0} return
  1004.     showVarValue $var
  1005. }
  1006.  
  1007. if {[info tclversion] < 8.0} {
  1008.     
  1009.     proc getVarFromList {{def ""}} {
  1010.     return [listpick -p {Which var?} -L $def [lsort -ignore [info globals]]]
  1011.     }
  1012.     
  1013. } else {
  1014.     
  1015.     proc getVarFromList {{def ""}} {
  1016.     set ns "[namespace qualifiers $def]"
  1017.     set def [namespace tail $def]
  1018.     
  1019.     set items {}
  1020.     foreach var [info vars "${ns}::*"] {
  1021.         lappend items [namespace tail $var]
  1022.     }
  1023.     foreach space [namespace children $ns] {
  1024.         lappend items "[namespace tail $space]::"
  1025.     }
  1026.     
  1027.     set items [concat "::" [lsort -ignore $items]]
  1028.     set var [listpick -p "Which var in namespace ${ns}::?" -L $def $items]
  1029.     if {$var == "::"} {
  1030.         set var [getVarFromList $ns]
  1031.     } elseif {[namespace qualifiers $var] != ""} {
  1032.         set var [getVarFromList "${ns}::${var}"]
  1033.     } else {
  1034.         set var "${ns}::${var}"
  1035.     }
  1036.     return $var
  1037.     }
  1038. }
  1039.  
  1040. #############################################################################
  1041. #  Report the current value of a global variable, chosen interactively
  1042. #  from a list of all active variables.
  1043. #
  1044. #  If the variable is an array, or its value is too big to fit in an 
  1045. #  alertnote, then its contents are listed in a new window, otherwise 
  1046. #  the variable's value is displayed in an alertnote.
  1047. #
  1048. proc showVarValue {var} {
  1049.     global $var
  1050.     if {![array exists $var]} {
  1051.         viewValue $var [set $var]
  1052.     } else {
  1053.     new -n "* $var *" -info [listArray $var]
  1054.     # if 'shrinkWindow' is loaded, call it to trim the output window.
  1055.     catch {shrinkWindow 2}
  1056.     }
  1057.  
  1058. #############################################################################
  1059. #  List the name and value of each element of the array $arrName.
  1060. #  (Convenient to use as a shell command.)
  1061. #
  1062. proc listArray {arrName} {
  1063.     global $arrName
  1064.     if {[array exists $arrName]} {
  1065.     set lines {}
  1066.         foreach nm [array names $arrName] {
  1067.             lappend lines "\"$nm\"\t\{[set ${arrName}($nm)]\}"
  1068.         }
  1069.         return [join $lines \r]
  1070.     } else {
  1071.         alertnote "\"$arrName\" doesn't exist in this context"
  1072.     }
  1073. }
  1074.  
  1075. # ◊◊◊◊ Marking ◊◊◊◊ #
  1076.  
  1077. ## 
  1078.  # -------------------------------------------------------------------------
  1079.  #     
  1080.  # "Tcl::parseFuncs" --
  1081.  #    
  1082.  # This proc is called by the "braces"    pop-up.    It returns a dynamically
  1083.  # created, alphabetical, list of "pseudo-marks".
  1084.  #    
  1085.  #    Author:    Tom Fetherston
  1086.  # -------------------------------------------------------------------------
  1087.  ## called by the "{}" button
  1088. proc Tcl::parseFuncs {} {
  1089.     global TclmodeVars
  1090.     set end [maxPos]
  1091.     set pos [minPos]
  1092.     set l {}
  1093.     set markExpr "^\[ \t\]*(itcl(::|_))?(class|body|proc|method|(config)?body)\[ \t\]"
  1094.     set appearanceList {}
  1095.     while {![catch {search -s -f 1 -r 1 -m 0 -i 0 "$markExpr" $pos} res]} {
  1096.     set start [lindex $res 0]
  1097.     set end [nextLineStart $start]
  1098.     set t [getText $start $end]
  1099.     append t "\}"
  1100.     set argLabel {}
  1101.     regsub "^itcl(::|_)" [lindex $t 0] "" what
  1102.     switch -- [lindex $t 0] {
  1103.         "proc" {
  1104.         append argLabel [set word [lindex $t 1]]
  1105.         #get the list of arguments
  1106.         set argsList [lindex $t 2]
  1107.         if {[llength $argsList] > 0} {
  1108.             append argLabel " \{"
  1109.             foreach arg $argsList {
  1110.             if {[llength $arg] == 2 } {
  1111.                 append argLabel "¿"
  1112.             } elseif {[set arg] != "args"} {
  1113.                 append argLabel "•"
  1114.             } else {
  1115.                 append argLabel "…"
  1116.             }
  1117.             }
  1118.             append argLabel "\}"                    
  1119.         } 
  1120.         }
  1121.         default {
  1122.         append argLabel [set word [lindex $t 1]]
  1123.         }
  1124.     }
  1125.     if {[info exists cnts($word)]} {
  1126.         # This section handles duplicate. i.e., overloaded names
  1127.         set cnts($word) [expr {$cnts($word) + 1}]
  1128.         set tailOfTag($word) " ($cnts($word) of $cnts($word))"
  1129.         # we want the tag to point to its last occurence 
  1130.         # because in Tcl, that proc will be 'in-force' when the
  1131.         # file is loaded.
  1132.         set indx($word) [lineStart [pos::math $start - 1]]
  1133.     } else {
  1134.         #SO do: remember the following
  1135.         set cnts($word) 1
  1136.         # if this is the only occurence of this proc, remember where it starts
  1137.         set indx($word) [lineStart [pos::math $start - 1]]
  1138.     }
  1139.     #associate name and tag
  1140.     set tag($word) $argLabel
  1141.     
  1142.     #advance pos to where we want to start the next search from
  1143.     set pos $end
  1144.     }
  1145.     
  1146.     set rtnRes {}
  1147.     
  1148.     if {[info exists indx]} {
  1149.     foreach hn [lsort -ignore [array names indx]] {
  1150.         set next [nextLineStart $indx($hn)]
  1151.         set completeTag [set tag($hn)]
  1152.         if {[info exists tailOfTag($hn)]} {
  1153.         append completeTag [set tailOfTag($hn)]
  1154.         }
  1155.         
  1156.         lappend rtnRes $completeTag $next
  1157.     }
  1158.     }
  1159.     return $rtnRes 
  1160. }
  1161.  
  1162. # called by the "M" button
  1163. proc Tcl::MarkFile {} {
  1164.     global structuralMarks
  1165.     set end [maxPos]
  1166.     set pos [minPos]
  1167.     set l {}
  1168.     if {$structuralMarks} {
  1169.     set markExpr {^;?[     ]*(itcl(::|_))?(class|namespace eval|proc|method|(config)?body|# ◊◊◊◊)[     ]}
  1170.     } else {
  1171.     set markExpr {^;?[     ]*(itcl(::|_))?(class|namespace eval|proc|method|(config)?body)[     ]}
  1172.     }
  1173.     set class ""
  1174.     set hasMarkers 0
  1175.     while {![catch {search -s -f 1 -r 1 -m 0 -i 0 "$markExpr" $pos} res]} {
  1176.     set start [lindex $res 0]
  1177.     set end [nextLineStart $start]
  1178.     set t [string trim [getText $start $end] ";"]
  1179.     append t "\}"
  1180.     if {[catch {lindex $t 0}]} {
  1181.         # wasn't a well formed list
  1182.         set pos $end
  1183.         continue
  1184.     }
  1185.     regsub "^itcl(::|_)" [lindex $t 0] "" what
  1186.     switch -glob $what {
  1187.         "proc" -
  1188.         "configbody" { set text [lindex $t 1] }
  1189.         "method" { set text ${class}::[lindex $t 1] }
  1190.         "body" { 
  1191.         regexp {[a-zA-Z_][a-zA-Z_/0-9]*::[a-zA-Z_][a-zA-Z_/0-9]* } \
  1192.           "[lindex $t 1] " text
  1193.         }
  1194.         "namespace" {
  1195.         set ns [lindex $t 2]
  1196.         if {[regexp {[^a-zA-Z0-9]} $ns]} {
  1197.             set pos $end
  1198.             continue
  1199.         }
  1200.         set text "${ns} 111" 
  1201.         }
  1202.         "*class" { 
  1203.         set class [lindex $t 1]
  1204.         set text "${class} 000" 
  1205.         }
  1206.         "#" { 
  1207.         regexp "# ◊◊◊◊ (.*) ◊◊◊◊" $t all text
  1208.         if {[regexp "^(    )|(    )# ◊◊◊◊ " $t]} {
  1209.             set text " •$text"
  1210.         } else {
  1211.             set text "•$text"
  1212.         }                
  1213.         set hasMarkers 1
  1214.         }
  1215.     }
  1216.     set pos $end
  1217.     if {$structuralMarks} {
  1218.         lappend asEncountered $text
  1219.         set arr inds
  1220.     } else {
  1221.         if {[string index $t 0] == ";"} {
  1222.         set arr iinds
  1223.         } else {
  1224.         set arr inds
  1225.         }
  1226.     }
  1227.     set ${arr}($text) [lineStart [pos::math $start - 1]]
  1228.     }
  1229.     
  1230.     set already ""
  1231.     set class "#"
  1232.     foreach arr {inds iinds} {
  1233.     if {[info exists $arr]} {
  1234.         if {$arr == "iinds"} {
  1235.         setNamedMark "-" 0 0 0
  1236.         }
  1237.         if {$structuralMarks} {
  1238.         set order $asEncountered
  1239.         } else {
  1240.         set order [lsort -ignore [array names $arr]]
  1241.         }
  1242.         foreach f $order {
  1243.         if {[set el [set ${arr}($f)]] != 0} {
  1244.             set next [nextLineStart $el]
  1245.         } else {
  1246.             set next 0
  1247.         } 
  1248.         
  1249.         if { [string first "000" $f] != -1 } {
  1250.             set ff "Class '[set class [lindex $f 0]]'"
  1251.         } elseif { [string first "111" $f] != -1 } {
  1252.             set ff "Namespace '[set class [lindex $f 0]]'"
  1253.         } elseif { [string first "${class}::" $f] == 0 } {
  1254.             set ff [string range $f [string length $class] end]
  1255.         } else {
  1256.             set ff $f
  1257.         }
  1258.         while { [lsearch -exact $already $ff] != -1 } {
  1259.             set ff "$ff "
  1260.         }
  1261.         lappend already $ff
  1262.         if {$hasMarkers && ![string match "•*" $ff] } {
  1263.             set ff " $ff"
  1264.         } 
  1265.         setNamedMark $ff $el $next $next
  1266.         }
  1267.     }
  1268.     }
  1269. }
  1270.  
  1271. # ◊◊◊◊ Misc. ◊◊◊◊ #
  1272.  
  1273. ## 
  1274.  # -------------------------------------------------------------------------
  1275.  # 
  1276.  # "bind::tclContinueComment" --
  1277.  # 
  1278.  #  exploits a "feature" in the code that makes a new line a comment whenever 
  1279.  #  you are 'inside' a comment. This proc puts a pound sign at the end of the 
  1280.  #  current line, backsteps, and creates a new line. With the pound sign 
  1281.  #  present you are considered to be in a comment, so the bind::CarriageReturn 
  1282.  #  in the proc, and any subsequent bind::CarriageReturn called by a press of  
  1283.  #  the return key will provide another comment line automatically until the 
  1284.  #  pound sign at the end of the line is removed (killLine is handy for this).
  1285.  # -------------------------------------------------------------------------
  1286.  ##
  1287. proc bind::tclContinueComment {} {
  1288.     insertText {#}
  1289.     backwardChar
  1290.     bind::CarriageReturn
  1291.     deleteChar
  1292. }
  1293. Bind '\r' <c> bind::tclContinueComment Tcl
  1294.  
  1295. proc evaluateLine { pos } {
  1296.     goto $pos
  1297.     beginningLineSelect
  1298.     endLineSelect
  1299.  
  1300.     uplevel \#0 evaluate
  1301. }
  1302.  
  1303. #◊◊◊◊> 
  1304.  
  1305. tcltk::evaluateRemoteSynchronise
  1306.  
  1307.